package org.batatasframework.support.type;

import java.util.ArrayList;
import java.util.List;

import org.batatasframework.support.database.FieldShiftable;

/**
 * <pre>
 * 这里是把一个数值类型转成一个选项的定义，如：
 * 状态，存储的类型为int，显示时需要根据定义的值的意义来显示，如显示应该为：草稿、正常、禁止等描述
 * 
 * 这里需要把值为字段串的也包含进来
 * </pre>
 * @author jackson
 *
 */
public abstract class OptionalType implements FieldShiftable{
	
	/**
	 * 用于渲染生成界面的组件的列表，
	 */
	protected final List<OptionalRenderable> items = new ArrayList<>();
	//不分组的情况
	protected final List<OptionalItem> sources = new ArrayList<>();
	
	private long max;
	private long min;
	
	/** 单选 */
	public static OptionalTypeSingle single(){
		return new OptionalTypeSingle();
	}
	
	/** 多选 */
	public static OptionalTypeMultiple multiple(){
		return new OptionalTypeMultiple();
	}
	
	public void clear(){
		min = 0L;
		max = 0L;
		items.clear();
		sources.clear();
	}
	
	@Override
	public long maxValue() {
		return max;
	}
	
	@Override
	public long minValue() {
		return min;
	}
	
	public int size(){
		return sources.size();
	}
	
	public boolean isEmpty(){
		return sources.isEmpty();
	}
	
	public abstract String show(long value);
	
	public abstract List<OptionalItem> find(long value);
	
	public void render(OptionalRender optionRender){
		for(OptionalRenderable it : items){
			it.render(optionRender);
		}
	}
	
	public List<OptionalItem> getSources() {
		return sources;
	}

	/**
	 * 注释说明的项
	 * @author jackson
	 *
	 */
	public class OptionalItemComment implements OptionalRenderable{

		protected final String name;
		
		protected OptionalItemComment(String name){
			this.name = name;
		}

		@Override
		public void render(OptionalRender optionRender) {
			optionRender.append(name);
		}

		@Override
		public String getName() {
			return name;
		}
	}
	/**
	 * 具体的一个选择项
	 * @author jackson
	 *
	 */
	public class OptionalItem implements OptionalEntry, OptionalRenderable, OptionalMatchable{

		protected final String name;
		
		protected final long value;
		
		/** 后缀，放在名字的后面的，可以另外定义，在某些情况下后缀是不需要现出的 */
		protected String suffix = "";
		
		protected OptionalItem(String name, long value){
			this.name = name;
			this.value = value;
			
			if(value < min)min = value; else if(value > max)max = value;
		}

		public OptionalItem resetValue(long value){
			return new OptionalItem(name, value, suffix);
		}
		
		protected OptionalItem(String name, long value, String suffix){
			this(name, value);
			
			setSuffix(suffix);
		}
		
		@Override
		public String getName() {
			return name;
		}
		
		public void setSuffix(String suffix) {
			if(null != suffix) this.suffix = suffix;
		}
		
		@Override
		public Long getValue() {
			return value;
		}
		
		@Override
		public String toString() {
			return name;
		}

		@Override
		public void render(OptionalRender optionRender) {
			optionRender.append(this);
		}

		@Override
		public boolean match(long optionValue) {
			return internalMatch(this, optionValue);
		}
	}
	
	/**
	 * 对选择项进行的分组
	 * @author jackson
	 *
	 */
	public final class OptionsGroup implements OptionalRenderable{
		private String name;
		private List<OptionalRenderable> items = new ArrayList<>();
		
		private OptionsGroup(String name){
			this.name = name;
		}
		
		public void add(String opt){
			_add(items, opt);
		}
		
		public String getName() {
			return name;
		}
		
		public List<OptionalRenderable> getItems() {
			return items;
		}

		@Override
		public void render(OptionalRender optionRender) {
			optionRender.append(name, "(");
			for(OptionalRenderable it : items){
				it.render(optionRender);
			}
			optionRender.append(')');
		}
	}
	
	protected abstract boolean internalMatch(OptionalItem item, long optionValue);
	
	public void add(OptionalItem oi){
		items.add(oi);
		sources.add(oi);
	}

	private OptionalItem _add(List<OptionalRenderable> items, String name, long value){
		OptionalItem oi = new OptionalItem(name, value);
		items.add(oi);
		
		//选项的源
		sources.add(oi);
		return oi;
	}
	
	private OptionalItem _add(List<OptionalRenderable> items, String opt){
		return _add(items, opt, sources.size());
	}
	
	public OptionalItem add(String name, long value){
		return _add(items, name, value);
	}
	
	public OptionalItem add(String opt){
		return _add(items, opt);
	}
	
	public OptionalType add(String...opts){
		for(String opt : opts){
			_add(items, opt);
		}
		return this;
	}
	
	public OptionsGroup group(String groupName){
		OptionsGroup og = new OptionsGroup(groupName);
		items.add(og);
		return og;
	}
	
	public OptionsGroup group(String groupName, String...items){
		OptionsGroup og = group(groupName);
		for(String opt : items){
			og.add(opt);
		}
		return og;
	}

}
